Skip to content

feat(image-editor): wire Marquee + Burn + Rotate View#43

Merged
lyfuci merged 1 commit intomainfrom
feat/image-editor-marquee-selection
Apr 24, 2026
Merged

feat(image-editor): wire Marquee + Burn + Rotate View#43
lyfuci merged 1 commit intomainfrom
feat/image-editor-marquee-selection

Conversation

@lyfuci
Copy link
Copy Markdown
Owner

@lyfuci lyfuci commented Apr 24, 2026

Summary

Three more PS-staple tools moved from stubs to functional. Bundled together because they're independent additions — no overlap in concerns or shared files beyond the usual i18n / palette / options-bar plumbing.

Marquee (M)

Real rectangular selection. Drag to define; selection persists in
`EditorState.selection` (history-tracked + .json round-trip); shown as
a static marching-ants outline (white dashes over a black halo for
legibility on any background). Cmd/Ctrl+A selects all,
Cmd/Ctrl+D deselects.

  • New `marquee-drawing` interaction kind in `Canvas.tsx`.
  • Selection lives in original-image preview-pixel space; parent shifts
    cropped-canvas coords back by the active crop origin before storing.
  • `render.ts` gains a `liveCanvas` flag (true on live preview, false on
    export) — gates marching-ants chrome so it never bakes into pixels.
  • `OptionsBar` marquee variant: hint text + "Deselect" button when a
    selection is active.
  • `serialize.ts` adds `selection` to the parsed state.

No tools yet act on the selection — that's a follow-up PR per tool
(bucket / brush / fill within selection, etc.). This PR establishes
the selection state + UI; downstream wiring is straightforward.

Burn

Mirror of Dodge (#42). New `'burn'` in the `Tool` union; the dodge
branch now handles both (white+`lighter` vs. black+`multiply`).
Palette gets a Moon icon next to the dodge Sun. Layer-list distinguishes
burn strokes.

Rotate View (R)

View-only canvas rotation. New `viewRotation` state (0/90/180/270) in
ImageEditor; Workspace applies it as a CSS `rotate()` on the wrapper
transform. Pixels untouched. Toggled by R OR by clicking the
palette button (intercepted in `trySetTool` since rotateView has no
"tool mode" — every click just cycles the rotation).

`STUB_TOOLS` shrinks: `marquee` and `rotateView` removed.

Branched from `main` (independent).

Test plan

  • Press M, drag — dashed marquee appears live; mouseup commits, marching-ants outline persists.
  • Cmd+D — selection clears.
  • Cmd+A — selection covers whole image.
  • Save .json with selection active → reload → selection restored.
  • Export PNG — marquee chrome NOT in the exported image.
  • Crop, then marquee inside — selection lands in the right place; persists after crop is cleared.
  • Click Burn palette button (Moon icon), drag — area visibly darkens; repeat strokes build up.
  • Layer panel labels: dodge stroke vs. burn stroke distinct.
  • Press R — workspace rotates 90°. Press 4× to return.
  • Click Rotate View palette button — same cycle.

🤖 Generated with Claude Code

Three more PS-staple tools moved out of the stub bucket. Bundled
together because they're independent additions that don't conflict.

## Marquee (M)

Adds a real marquee selection. Drag-to-define a rectangular selection;
the selection persists in `EditorState.selection` (history-tracked, .json
round-trip), shown as a static marching-ants outline (white dashes over
black halo). Cmd/Ctrl+A select all (full canvas), Cmd/Ctrl+D deselect.

- New `Interaction` kind in Canvas: `marquee-drawing` (mousedown → start;
  mousemove → update; mouseup commits via `onCommitSelection` if the
  drag is non-trivial). Live preview rendered after `renderTo` so it
  sits above all other content.
- `EditorState.selection` lives in original-image preview-pixel space;
  parent shifts cropped-canvas coords back by the active crop origin
  before storing.
- `render.ts` gains a `liveCanvas` flag (true on the live preview, false
  on export) — gates marching-ants chrome so it never bakes into pixels.
- `OptionsBar` marquee variant: hint text + "Deselect" button when a
  selection is active.
- `serialize.ts` adds `selection` to the parsed state.

## Burn

Mirror of Dodge from PR #42. New `'burn'` value in the `Tool` union;
`Canvas.tsx`'s dodge branch now handles dodge OR burn (white+lighter
vs. black+multiply). Palette gets a Moon icon next to the dodge Sun.
`OptionsBar` shares the brush variant with a burn-specific hint.
Layer-list label distinguishes burn strokes.

## Rotate View (R)

View-only canvas rotation. New `viewRotation` state (0/90/180/270) in
ImageEditor; Workspace applies it as a CSS `rotate()` on the wrapper
transform. Pixels are not modified — purely a viewing aid. Toggled by
the R keyboard shortcut OR by clicking the palette button (intercepted
in `trySetTool` since rotateView has no "tool mode" — every click just
cycles the rotation).

`STUB_TOOLS` shrinks: `marquee` and `rotateView` removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lyfuci lyfuci merged commit 0a3efc7 into main Apr 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant